package org.iabako.server.controller.timer.business;

import org.apache.log4j.Logger;
import org.iabako.server.conf.AppConf;
import org.iabako.server.dao.business.NotificationDAO;
import org.iabako.server.dao.user.EnterpriseDAO;
import org.iabako.server.mail.IabakoMailHelper;
import org.iabako.server.mail.IabakoMailSender;
import org.iabako.server.mail.template.NotificationEmailTemplate;
import org.iabako.server.tools.BundleMessages;
import org.iabako.server.tools.ServerTools;
import org.iabako.shared.entity.business.Notification;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.entity.user.User;
import org.iabako.shared.iservice.business.NotificationService;
import org.iabako.shared.iservice.user.UserService;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jose on 19/03/15.
 */

@Controller
public class SendNotificationRecapControllerTimer {

    static Logger log = Logger.getLogger(SendNotificationRecapControllerTimer.class.getName());

    @Autowired
    EnterpriseDAO enterpriseDAO;
    @Autowired
    NotificationDAO notificationDAO;
    @Autowired
    NotificationService notificationService;
    @Autowired
    UserService userService;
    @Autowired
    IabakoMailSender iabakoMailSender;
    @Autowired
    private AppConf appConf;
    @Autowired
    NotificationEmailTemplate notificationEmailTemplate;
    @Autowired
    BundleMessages messages;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    //Every day at 01:30 AM
    @Scheduled(cron = "0 30 1 * * ?")
    //@Scheduled(initialDelay = 10000, fixedRate = 120000)
    public void action() throws Exception {
        log.info("Executing SendNotificationRecapControllerTimer...");

        List<Enterprise> enterpriseList = enterpriseDAO.getEnterpriseWithoutNotificationEmail();
        log.info("Enterprises to check : " + enterpriseList.size());

        Map<User, List<Notification>> usersNotificationBefore = new HashMap<User, List<Notification>>();
        for (Enterprise e : enterpriseList) {
            for (User u : e.getUsers()) {
                if (u.getLastNotificationEmail() != null
                        && u.getLastNotificationEmail().compareTo(new ServerTools().resetTime(new Date())) >= 0) {
                    //Email already sent
                    continue;
                }
                Date lastNotificationCalculation = u.getEnterprise().getLastNotificationCalculation();
                List<Notification> notificationsBefore;

                if (lastNotificationCalculation == null || u.getLastLogin() == null
                        || u.getLastLogin().compareTo(lastNotificationCalculation) > 0) {
                    //User has logged in after last notification calculation (always the case if enterprise has just one user)
                    //Then, we take actual notifications as reference
                    notificationsBefore = notificationService.getNotificationsByUser(u);
                } else {
                    //User HAS NOT logged in after last notification calculation
                    //Then, we take the last email notifications as reference
                    notificationsBefore = notificationDAO.getEmailNotifications(u);
                }
                usersNotificationBefore.put(u, notificationsBefore);
            }
        }

        for (Enterprise e : enterpriseList) {
            userService.reloadNotifications(e, false);
        }

        log.info("Users to check : " + usersNotificationBefore.size());

        for (User u : usersNotificationBefore.keySet()) {
            List<Notification> notificationsBefore = usersNotificationBefore.get(u);
            List<Notification> notificationsAfter = notificationService.getNotificationsByUser(u);

            NotificationEmailTemplate template = notificationEmailTemplate.getInstance(u.getEnterprise(), notificationsBefore,
                    notificationsAfter, u.getFirstName());

            if (template != null) {
                //New notifications were detected, we must send an email

                IabakoMailHelper mailHelper = new IabakoMailHelper(appConf.getNoReplyEmail(),
                        appConf.getEmailPersonalFrom(), u.getEmail(), messages.getLabel(u.getEnterprise().getLanguage(), "notification_email_subject",
                        u.getFirstName(), GenericTools.formatDate(new Date())), null);
                mailHelper.setTemplate(template);

                if (iabakoMailSender.sendMail(mailHelper)) {
                    u.setLastNotificationEmail(new Date());
                }
            }

            //In all cases, we persist new notifications (because old ones were deleted by userService.reloadNotifications(...)
            notificationDAO.saveEmailNotifications(u, notificationsAfter);
        }

        for (Enterprise e : enterpriseList) {
            //Merge notifications calculation in Enterprise entity and lastNotificationEmail in User entity (by cascading)
            enterpriseDAO.merge(e);
        }
        log.info("SendNotificationRecapControllerTimer ends successfully");
    }
}
